package com.lct.simpleforecast.ui.activity

import android.Manifest
import android.support.v7.widget.LinearLayoutManager
import android.view.KeyEvent
import com.afollestad.materialdialogs.DialogAction
import com.afollestad.materialdialogs.MaterialDialog
import com.lct.simpleforecast.ActivityManager
import com.lct.simpleforecast.AppConstant
import com.lct.simpleforecast.R
import com.lct.simpleforecast.bean.ForecastBean
import com.lct.simpleforecast.delegates.DelegatesExt
import com.lct.simpleforecast.mvp.presenter.MainPresenter
import com.lct.simpleforecast.mvp.view.IMainView
import com.lct.simpleforecast.ui.activity.base.BaseActivity
import com.lct.simpleforecast.ui.adapter.ForecastAdapter
import kotlinx.android.synthetic.main.activity_main.*
import org.jetbrains.anko.startActivity
import org.jetbrains.anko.toast
import kotlin.properties.Delegates

class MainActivity : BaseActivity(), IMainView {
    companion object {
        //用于判断哪种情况下发生的网络错误
        const val FIRST_LOCATION = "MainActivity:firstLocation"
        const val GET_FORECAST_DATA = "MainActivity:getForecastData"
    }

    //点击返回键时的时间戳
    private var clickBackTime = 0L
    //当前的位置
    private var currentLocation: String by DelegatesExt.preference(AppConstant.SP_KEY_LOCATION,
            "")
    //旧的位置，用于和当前的位置做比较，判断位置是否发生变化，
    //位置不发生变化则不需要在onResume方法中重新获取数据
    private var oldLocation = ""

    private val presenter = MainPresenter()
    private val dailyForecastList: MutableList<ForecastBean.HeWeather.DailyForecast> by lazy {
        arrayListOf<ForecastBean.HeWeather.DailyForecast>()
    }
    private var forecastAdapter: ForecastAdapter by Delegates.notNull()

    //哪种情况下发生的网络不可用
    private var whichSituation = ""

    override fun onResume() {
        super.onResume()
        if (currentLocation != "" && oldLocation != currentLocation) {
            //已经设置位置，并且MainActivity首次启动或者选择的位置发生变化，加载新数据
            setTitle(currentLocation)
            oldLocation = currentLocation
            presenter.getForecastData(currentLocation)
        }
    }

    override fun onDestroy() {
        super.onDestroy()
        presenter.detachView()
    }

    override fun onKeyDown(keyCode: Int, event: KeyEvent?): Boolean {
        if (keyCode == KeyEvent.KEYCODE_BACK) {
            if (clickBackTime + 2000 >= System.currentTimeMillis()) {
                ActivityManager.instance.appExit(this, false)
            } else {
                toast(R.string.click_again)
            }
            clickBackTime = System.currentTimeMillis()
            return true
        }
        return super.onKeyDown(keyCode, event)
    }

    /**
     * 设置activity的布局
     */
    override fun setLayoutResId(): Int {
        return R.layout.activity_main
    }

    /**
     * 初始化数据
     */
    override fun initData() {
        //toolbar
        initToolbarMenu()
        //presenter
        presenter.attachView(this)
        //adapter
        rvForecast.layoutManager = LinearLayoutManager(this)
        forecastAdapter = ForecastAdapter(R.layout.rv_forecast_item, dailyForecastList)
        {
            startActivity<DetailActivity>(
                    DetailActivity.LOCATION to currentLocation,
                    DetailActivity.DATE to it.date,
                    DetailActivity.ICON to it.iconUrl(),
                    DetailActivity.DAY_DES to it.cond_txt_d,
                    DetailActivity.NIGHT_DES to it.cond_txt_n,
                    DetailActivity.TEMP_MAX to it.tmp_max,
                    DetailActivity.TEMP_MIN to it.tmp_min,
                    DetailActivity.WIND_DIRECTION to it.wind_dir,
                    DetailActivity.WIND_LEVEL to it.wind_sc)
        }
        rvForecast.adapter = forecastAdapter
        //启动定位
        startLocation()
    }

    /**
     * 进行定位，改方法不要放在onResume中执行，因为有申请权限的代码
     */
    private fun startLocation() {
        //申请定位需要的权限(位置、存储、手机状态)
        val permissions = arrayOf(Manifest.permission.ACCESS_FINE_LOCATION,
                Manifest.permission.WRITE_EXTERNAL_STORAGE,
                Manifest.permission.READ_PHONE_STATE)
        requestPermissions(permissions) {
            //启动定位
            presenter.startLocation(currentLocation)
        }
    }

    override fun initListener() {
        super.initListener()
        refreshLayout.setOnRefreshListener {
            presenter.getForecastData(currentLocation, true)
        }
    }

    /**
     * 网络由不可用变为可用后执行的操作
     *
     * 该类中由以下两种情况触发该方法：
     * 1.暂未设置位置进行定位时网络不可用
     * 2.加载天气数据时网络不可用
     */
    override fun afterNetworkAvailable() {
        super.afterNetworkAvailable()
        if (whichSituation == GET_FORECAST_DATA) {
            //重新加载天气数据
            presenter.getForecastData(currentLocation)
        } else if (whichSituation == FIRST_LOCATION) {
            //暂未设置位置，重新定位，此时的currentLocation为 ""
            presenter.startLocation(currentLocation)
        }
    }

    /**
     * 用户拒绝申请的权限，然后通过点击设置去设置权限，最后返回本页面时触发的方法
     */
    override fun afterSettingPermissions() {
        super.afterSettingPermissions()
        //设置过权限之后，再次启动定位
        startLocation()
    }

    /**
     * 设置标题
     *
     * @param locationInfo 位置信息
     */
    override fun setTitle(locationInfo: String) {
        toolbar?.title = locationInfo
    }

    /**
     * 暂未设置位置，定位时的loading
     *
     * @param loadingText 定位时的文本描述
     */
    override fun onLocationLoading(loadingText: String) {
        showLoadingView(loadingText)
    }

    /**
     * 暂未设置位置，定位成功后获取天气数据
     *
     * @param locationInfo 定位的信息
     */
    override fun onLocationSuccess(locationInfo: String) {
        currentLocation = locationInfo
        oldLocation = currentLocation
        presenter.getForecastData(locationInfo)
    }

    /**
     * 暂未设置位置，定位失败
     *
     * @param locationErrorMsg 定位错误信息
     */
    override fun onLocationFail(locationErrorMsg: String) {
        hideLoadingView()
        showLocationFailDialog()
    }

    /**
     * 定位失败提示框
     */
    private fun showLocationFailDialog() {
        MaterialDialog.Builder(this)
                .title(R.string.dialog_title)
                .content("")
                .negativeText(R.string.cancel)
                .positiveText(R.string.ok)
                .onAny { _, which ->
                    if (which == DialogAction.POSITIVE) {
                        //打开SettingActivity
                        startActivity<SettingActivity>()
                    } else {
                        //退出应用
                        ActivityManager.instance.appExit(this, false)
                    }
                }
                .build()
                .show()
    }

    /**
     * 位置发生变化
     *
     * @param newLocation 新的位置
     */
    override fun onLocationChange(newLocation: String) {
        currentLocation = newLocation
        oldLocation = currentLocation
        presenter.getForecastData(newLocation)
    }

    /**
     * 网络不可用
     *
     * 该页面中由两种情况下触发本方法：
     * 1.暂未设置位置进行定位时网络不可用
     * 2.加载天气数据时网络不可用
     *
     * @param mark 标记哪种情况下发生的网络不可用
     * @param isRefresh 是否是刷新的回调（true是刷新的回调，false第一次加载的回调）
     */
    override fun onNetWorkError(mark: String, isRefresh: Boolean) {
        whichSituation = mark
        if (isRefresh) {
            refreshLayout.finishRefresh(false)
        }
        showNetworkErrorView()
    }

    /**
     * 数据加载成功
     *
     * @param t 实体类对象
     * @param isRefresh 是否是刷新的回调（true是刷新的回调，false第一次加载的回调）
     */
    override fun <T> onLoadSuccess(t: T, isRefresh: Boolean) {
        with(t as ForecastBean) {
            dailyForecastList.clear()
            dailyForecastList.addAll(dailyForecastList())
            forecastAdapter.notifyDataSetChanged()
            if (isRefresh) {
                refreshLayout.finishRefresh(true)
            }
        }
    }

    /**
     * 数据加载失败
     *
     * @param errorMsg 错误信息
     * @param isRefresh 是否是刷新的回调（true是刷新的回调，false第一次加载的回调）
     */
    override fun onLoadFailure(errorMsg: String, isRefresh: Boolean) {
        if (isRefresh) {
            refreshLayout.finishRefresh(false)
        } else {
            showLoadingFailView {
                presenter.getForecastData(currentLocation)
            }
        }
    }

    /**
     * 显示加载loading
     */
    override fun showLoading() {
        showLoadingView()
    }

    /**
     * 隐藏加载loading
     */
    override fun hideLoading() {
        hideLoadingView()
    }
}
